package jmai.scanner;

/**
 * @author - SDavis 4/2009
 * This class represents the AST Tree structure.
 */
public class ASTTree {

	/** number of pairs under the root node of the tree */
    private int numberOfPairs;
    
    /** boolean for whether tree has a begin pattern/action */
    private boolean hasBeginAction;

    /** boolean for whether tree has an end pattern/action */
    private boolean hasEndAction;

    /** root node */
    private ASTNode rootNode;

    /**
     * This is the constructor for the ASTTree class.
     */     
    public ASTTree() {

        numberOfPairs = 0;
        hasBeginAction = false;
        hasEndAction = false;

        rootNode = new ASTNode(ASTNode.ASTNodeType.ROOTNODE);

    }

    /**
     * @param inNumberOfPairs - number of pairs in the tree
     * This module sets the number of pairs in the tree.
     */     
    public void SetNumberOfPairs(int inNumberOfPairs) {

        numberOfPairs = inNumberOfPairs;

    }

    /**
     * @return number of pairs in the tree
     * This module gets the number of pairs in the tree.
     */     
    public int GetNumberOfPairs() {

        return numberOfPairs;

    }  

    /**
     * @param inHasBeginAction - boolean for begin pattern/action
     * This module sets the boolean for begin pattern/action.
     */     
    public void SetHasBeginAction(boolean inHasBeginAction) {

        hasBeginAction = inHasBeginAction;

    }

    /**
     * @return boolean for begin pattern/action
     * This module gets the boolean for begin pattern/action.
     */
    public boolean GetHasBeginAction() {

        return hasBeginAction;

    }  

    /**
     * @param inHasEndAction - boolean for end pattern/action
     * This module sets the boolean for end pattern/action.
     */    
    public void SetHasEndAction(boolean inHasEndAction) {

        hasEndAction = inHasEndAction;

    }

    /**
     * @return boolean for end pattern/action
     * This module gets the boolean for end pattern/action.
     */   
    public boolean GetHasEndAction() {

        return hasEndAction;

    }  

    /**
     * @param inPairType - pair node type
     * @return index of the new pair node in the tree
     * This module adds a pair node to the tree.
     */   
    public int AddPairNode(String inPairType) {

        rootNode.AddChildNode(new ASTNode(ASTNode.ASTNodeType.PAIRNODE));
        rootNode.GetChildNode(numberOfPairs).SetNodeData(inPairType);
        numberOfPairs = numberOfPairs + 1;

        /** setting the has begin action boolean as necessary */
        if (inPairType.equals("Begin")) {
            hasBeginAction = true;
        }

        /** setting the has end action boolean as necessary */
        if (inPairType.equals("End")) {
            hasEndAction = true;
        }

        return numberOfPairs - 1;

    }

    /**
     * @param inPairIndex - index of pair in tree
     * @param inRegEx - string for regular expression
     * This module sets the regular expression for a pair node of the tree.
     */    
    public void AddRegEx(int inPairIndex, String inRegEx) {

        rootNode.GetChildNode(inPairIndex).AddChildNode(new ASTNode(ASTNode.ASTNodeType.REGEXNODE));       
        rootNode.GetChildNode(inPairIndex).GetChildNode(0).SetNodeData(inRegEx);

    }

    /**
     * @param inPairIndex - index of pair in tree
     * @param inAction - string for action
     * @param inParameterOne - string for first parameter of action
     * @param inParameterTwo - string for second parameter of action
     * This module adds an action with parameters to a pair node of the tree.
     */ 
    public void AddAction(int inPairIndex, String inAction, String inParameterOne, String inParameterTwo) {

	int numberOfActions;

        rootNode.GetChildNode(inPairIndex).AddChildNode(new ASTNode(ASTNode.ASTNodeType.ACTIONNODE));
        numberOfActions = rootNode.GetChildNode(inPairIndex).GetNodeChildren().size();
        rootNode.GetChildNode(inPairIndex).GetChildNode(numberOfActions - 1).SetNodeData(inAction); 
        rootNode.GetChildNode(inPairIndex).GetChildNode(numberOfActions - 1).AddChildNode(new ASTNode(ASTNode.ASTNodeType.PARAMETERNODE));
        rootNode.GetChildNode(inPairIndex).GetChildNode(numberOfActions - 1).GetChildNode(0).SetNodeData(inParameterOne);
        rootNode.GetChildNode(inPairIndex).GetChildNode(numberOfActions - 1).AddChildNode(new ASTNode(ASTNode.ASTNodeType.PARAMETERNODE));
        rootNode.GetChildNode(inPairIndex).GetChildNode(numberOfActions - 1).GetChildNode(1).SetNodeData(inParameterTwo);

    }

    /**
     * @param inPairType - pair node type
     * @return type of pair node
     * This module get the type of a pair node.
     */     
    public String GetPairType(int inPairIndex) {

        return rootNode.GetChildNode(inPairIndex - 1).GetNodeData();

    }

    /**
     * @param inPairIndex - index of pair in tree
     * @return string for regular expression
     * This module gets the regular expression for a pair node of the tree.
     */       
    public String GetRegEx(int inPairIndex) {

        return rootNode.GetChildNode(inPairIndex - 1).GetChildNode(0).GetNodeData();

    }    

    /**
     * @param inPairIndex - index of pair in tree
     * @return the number of pair nodes as integer
     * This module gets the number of pair nodes of the tree.
     */       
    public int GetNumberOfActions(int inPairIndex) {

        return rootNode.GetChildNode(inPairIndex - 1).GetNodeChildren().size() - 1;

    }

    /**
     * @param inPairIndex - index of pair in tree
     * @param inActionIndex - index of action in pair
     * @return the action as a string
     * This module gets one of the actions of a pair node.
     */      
    public String GetAction(int inPairIndex, int inActionIndex) {

        return rootNode.GetChildNode(inPairIndex - 1).GetChildNode(inActionIndex).GetNodeData();

    }

    /**
     * @param inPairIndex - index of pair in tree
     * @param inActionIndex - index of action in pair
     * @return the first parameter of the action
     * This module gets the first parameter one of the actions of a pair node.
     */       
    public String GetFirstParameter(int inPairIndex, int inActionIndex) {

        return rootNode.GetChildNode(inPairIndex - 1).GetChildNode(inActionIndex).GetChildNode(0).GetNodeData();

    }

    /**
     * @param inPairIndex - index of pair in tree
     * @param inActionIndex - index of action in pair
     * @return the second parameter of the action
     * This module gets the second parameter one of the actions of a pair node.
     */    
    public String GetSecondParameter(int inPairIndex, int inActionIndex) {

        return rootNode.GetChildNode(inPairIndex - 1).GetChildNode(inActionIndex).GetChildNode(1).GetNodeData();

    }
    
    /**
     * This module prints out a mapping of the tree to the console.
     */    
    public void OutputTree() {

    	System.out.println("Program Abstract Syntax Tree:");
    	System.out.println("-----<Program Root>");
    	
    	for (int i = 1; i <= numberOfPairs; i++) {
    		OutputPair(i);
    	}
    	
    }
    
    /**
     * @param inPairIndex - index of the pair in the tree
     * This module prints out a mapping of a pair in a tree to the console.
     */    
    public void OutputPair(int inPairIndex) {
    	
    	String currentAction = new String();
    	currentAction = "";
    	
    	System.out.println("----------<Pair " + inPairIndex + " - " + GetPairType(inPairIndex) + ">");
    	
    	if (GetPairType(inPairIndex) == "RegEx") {
    		System.out.println("---------------<RegEx - " + GetRegEx(inPairIndex) + ">");
    	}
    	
    	for (int i = 1; i <= GetNumberOfActions(inPairIndex); i++) {
    		
    		currentAction = GetAction(inPairIndex, i);
    		System.out.println("---------------<Action - " + currentAction + ">");
    		
    		if (currentAction.equals("print") || currentAction.equals("remove")) {
    			System.out.println("--------------------<Parameter 1 - " + GetFirstParameter(inPairIndex, i) + ">");
    		}
    		else {
    			System.out.println("--------------------<Parameter 1 - " + GetFirstParameter(inPairIndex, i) + ">");
    			System.out.println("--------------------<Parameter 2 - " + GetSecondParameter(inPairIndex, i) + ">");    			
    		}
    		
    	}
    	
    }
    
    /**
     * This module removes the last pair node from a tree.
     */    
    public void RemoveLastPairNode() {
    	
    	rootNode.RemoveLastChildNode();
    	numberOfPairs = numberOfPairs - 1;
    	
    }

}
